import asyncio
import logging
import os

from sqlalchemy.ext.asyncio import AsyncSession
from rapidfuzz import process, utils, fuzz
from rapidfuzz.distance import Levenshtein

from price_analysis.api_v1.processing_data import crud
from price_analysis.core.config import settings
from price_analysis.utils.file_support import write_ocr_file, JsonFileSupport


logger = logging.getLogger("main")
logger_process = logger.getChild("processing-data")


async def check_item(
    item: dict,
    all_data_in_FSSC: list[str],
    session: AsyncSession,
) -> str | None:
    description = item["Description"]
    model = item["Model"]
    provider = item["Provider"]

    if provider:
        logger_process.info(f"Поиск по производителю и модели")
        materials: list[str] = await crud.get_materials_by_param(
            session=session, param=provider
        )
        if materials:
            search_result = process.extractOne(
                model,
                materials,
                scorer=fuzz.token_set_ratio,
                processor=utils.default_process,
                score_cutoff=55,
            )
            if search_result:
                return search_result[0]

    logger_process.info(f"Выборка по описанию")
    query: list[tuple] = process.extract(
        description,
        all_data_in_FSSC,
        scorer=fuzz.token_set_ratio,
        processor=utils.default_process,
    )

    relevant_materials: list[str] = [str(item[0]) for item in query]

    if not relevant_materials:
        return None

    logger_process.info(f"Выбор из выборки по описанию")
    search_result = process.extractOne(
        description,
        relevant_materials,
        scorer=Levenshtein.normalized_similarity,
        score_cutoff=0.45,
    )

    if search_result:
        return search_result[0]

    return None


async def search_data_in_FSSC2020(
    in_data: list[dict],
    session: AsyncSession,
) -> None:
    logger_process.info("Начат поиск номенклатуры в сборнике ФССЦ")

    full_path_in_fssc = os.path.join(settings.ocr_data_path, "in_fssc" + ".json")
    full_path_to_request_prices = os.path.join(
        settings.ocr_data_path, "to_request_prices" + ".json"
    )

    if os.path.isfile(full_path_in_fssc) and os.path.isfile(
        full_path_to_request_prices
    ):
        logger_process.info("Файл с данными уже существует")
        return

    in_fssc = []
    to_request_prices = []
    all_data_in_FSSC = await crud.get_materials(session=session)

    for data_item in in_data:
        rows: list[dict] = data_item["data"]

        for index, row in enumerate(rows):
            name_in_fssc = await check_item(
                item=row,
                all_data_in_FSSC=all_data_in_FSSC,
                session=session,
            )

            if name_in_fssc:
                row["id"] = index
                row["name_in_fssc"] = name_in_fssc
                row["idex_in_fssc"] = await crud.get_material_index_in_FSSC(
                    session=session, name=name_in_fssc
                )
                in_fssc.append(row)
            else:
                row["section_title"] = data_item["section"]["title"]
                to_request_prices.append(row)

    logger_process.info(
        "Поиск номенклатуры в сборнике ФССЦ закончен, начата запись данных"
    )

    data_in_fssc = JsonFileSupport(full_path_in_fssc)
    data_to_request_prices = JsonFileSupport(full_path_to_request_prices)

    await asyncio.gather(
        data_in_fssc.write_json_file(in_fssc),
        data_to_request_prices.write_json_file(to_request_prices),
    )

    logger_process.info("Данные записаны")
